<?php
/**
*
* @package YubiKey Login
* @version 1.0.3
* @copyright (c) 2010 Tim Schlueter
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
*
*/

/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
	exit;
}

if (!function_exists('delete_yubikey'))
{
	include "{$phpbb_root_path}includes/functions_yubikey_login.$phpEx";

	function yubikey_message($message, $action = null, $trigger_error = true, $warn = false, $admin = false)
	{
		global $user;

		$message = (isset($user->lang[$message])) ? $user->lang[$message] : $message;
		if ($admin)
		{
			$action = ($action != null) ? adm_back_link($action) : '';
		}
		else
		{
			$action = ($action != null) ? '' : $user->page['page'];
		}

		if ($trigger_error)
		{
			if ($warn)
			{
				trigger_error($message . $action, E_USER_WARNING);
			}
			else
			{
				trigger_error($message . $action);
			}
		}
		else
		{
			if ($warn)
			{
				add_error_message($message);
			}
			else
			{
				add_message($message);
			}
		}
	}

	function insert_yubikey($deviceid, $user_id)
	{
		global $db;

		$data = array(
			'deviceid'	=> $db->sql_escape($deviceid),
			'user_id'	=> (int) $user_id,
			'lastseen'	=> 0
		);
		$sql = 'INSERT INTO ' . YUBIKEY_TABLE . ' ' . $db->sql_build_array('INSERT', $data);
		$db->sql_query($sql);

		if ($db->sql_affectedrows())
		{
			// Log the action
			add_log('user', $user_id, 'LOG_YUBIKEY_ADDED', $deviceid);

			return true;
		}
		else
		{
			// Log the action
			add_log('user', $user_id, 'LOG_ERROR_ADDING_YUBIKEY', $deviceid);

			return false;
		}
	}

	function add_yubikey($otp, $user_id)
	{
		global $config, $db, $phpbb_root_path, $phpEx, $user;

		// Check if OTP is valid YubiKey OTP
		$deviceid = yubikey_is_otp($otp);
		if(!$deviceid)
		{
			yubikey_message('LOGIN_ERROR_YUBIKEY_BAD_OTP', null, false, true, false);
			return false;
		}

		// Validate OTP
		$otp_val_status = yubikey_validate_otp($otp); // false if success

		if ($otp_val_status)
		{
			$err = $otp_val_status;

			if (isset($user->lang[$err]))
			{
				$err = $user->lang[$err];
			}

			// Assign admin contact to some error messages
			if (substr_count($err, '%s') == 2)
			{
				$err = (!$config['board_contact']) ? sprintf($err, '', '') : sprintf($err, '<a href="mailto:' . htmlspecialchars($config['board_contact']) . '">', '</a>');
			}
			yubikey_message($err, null, false, true, false);
			return false;
		}
		else
		{
			// Check if YubiKey already exists
			$row = yubikey_get_details($deviceid);
			if ($row)
			{
				yubikey_message('ERROR_YUBIKEY_ALREADY_EXISTS', null, false, true, false);
				return false;
			}
			else
			{
				if(insert_yubikey($deviceid, $user_id))
				{
					yubikey_message('YUBIKEY_ADDED', null, false);
					return true;
				}
				else
				{
					yubikey_message('ERROR_ADDING_YUBIKEY', null, false);
					return false;
				}
			}
		}
	}

	function reset_yubikey($otp, $user_id)
	{
		global $config, $db, $phpbb_root_path, $phpEx, $user;

		$error_msg = '';

		// Check if OTP is valid YubiKey OTP
		$deviceid = yubikey_is_otp($otp);
		if(!$deviceid)
		{
			return array(
				'status'	=> false,
				'error_msg'	=> 'LOGIN_ERROR_YUBIKEY_BAD_OTP',
			);
		}

		// Validate OTP
		$otp_val_status = yubikey_validate_otp($otp); // false if success

		if ($otp_val_status)
		{
			$err = $otp_val_status;

			if (isset($user->lang[$err]))
			{
				$err = $user->lang[$err];
			}

			// Assign admin contact to some error messages
			if (substr_count($err, '%s') == 2)
			{
				$err = (!$config['board_contact']) ? sprintf($err, '', '') : sprintf($err, '<a href="mailto:' . htmlspecialchars($config['board_contact']) . '">', '</a>');
			}

			$error_msg = $err;
		}
		else
		{
			// Check if YubiKey already exists and belongs to some other user
			$yubikey_exists = false;

			$deviceid = yubikey_get_deviceid($otp);
			$row = yubikey_get_details($deviceid);
			if($row)
			{
				$yubikey_exists = true;
				if($row['user_id'] != (int) $user_id)
				{
					return array(
						'status'	=> false,
						'error_msg'	=> ERROR_YUBIKEY_ALREADY_EXISTS,
					);
				}
			}

			// Reset the lost yubikey tokens
			$sql = 'UPDATE ' . YUBIKEY_TABLE . ' SET lost_key = NULL WHERE user_id = ' . (int) $user_id;
			$db->sql_query($sql);
			$affected[0] = $db->sql_affectedrows();

			if ($yubikey_exists)
			{
				$sql  = ' UPDATE ' . YUBIKEY_TABLE . ' SET status = ' . YUBIKEY_ACTIVE;
				$sql .= ' WHERE deviceid = \'' . $db->sql_escape($deviceid) . '\' AND user_id = ' . (int) $user_id;
				$db->sql_query($sql);
				$affected[1] = $db->sql_affectedrows();

				if ($affected[1] > 0)
				{
					// Log the action
					add_log('user', $user_id, 'LOG_YUBIKEY_ACTIVATED', $deviceid);
				}
				else
				{
					// Log the action
					add_log('user', $user_id, 'LOG_ERROR_ACTIVATING_YUBIKEY', $deviceid);
				}
			}
			else
			{
				if(insert_yubikey($deviceid, $user_id))
				{
					$affected[1] = 1;

					yubikey_message('YUBIKEY_ADDED', null, false);
					return true;
				}
				else
				{
					$affected[1] = 0;

					yubikey_message('ERROR_ADDING_YUBIKEY', null, false);
					return false;
				}
			}
			if ($affected[0] > 0 && $affected[1] > 0)
			{
				// Log the action
				add_log('user', $user_id, 'LOG_YUBIKEY_RESET_DONE', $deviceid);
			}
		}
		$status = ($error_msg != '')?false:true;
		return array(
			'status'	=> $status,
			'error_msg'	=> $error_msg,
		);
	}

	function activate_deactivate_yubikey($yubikey, $status = YUBIKEY_ACTIVE, $action = null, $trigger_error = false, $admin = false)
	{
		global $db, $user;

		// Check if YubiKey exists
		$row = yubikey_get_details($yubikey);

		$user_id = (int) $row['user_id'];

		if ($user_id != $user->data['user_id'] && !$admin)
		{
			yubikey_message('YUBIKEY_ERROR_INVALID', $action, $trigger_error, true, $admin);
		}

		// Activate/deactivate the YubiKey
		$sql = 'UPDATE ' . YUBIKEY_TABLE . ' SET status = ' . $status  . ' WHERE deviceid = \'' . $db->sql_escape($yubikey) . '\'';
		$db->sql_query($sql);

		if ($db->sql_affectedrows())
		{
			// Log the action
			$log_action = 'LOG_YUBIKEY_' . (($status == YUBIKEY_INACTIVE) ? 'DE' : '') . 'ACTIVATED';
			if ($admin)
			{
				add_log('admin', $log_action, $yubikey);
			}
			add_log('user', $user_id, $log_action, $yubikey);

			$message = 'YUBIKEY_' . (($status == YUBIKEY_INACTIVE) ? 'DE' : '') . 'ACTIVATED';
			yubikey_message($message, $action, $trigger_error, false, $admin);
		}
		else
		{
			// Log the action
			$log_action = 'LOG_ERROR_' . (($status == YUBIKEY_INACTIVE) ? 'DE' : '') . 'ACTIVATING_YUBIKEY';
			add_log('user', $user_id, $log_action, $yubikey);

			$message = 'ERROR_' . (($status == YUBIKEY_INACTIVE) ? 'DE' : '') . 'ACTIVATING_YUBIKEY';
			yubikey_message($message, $action, $trigger_error, true, $admin);
		}
	}

	function delete_yubikey($yubikeys, $action = null, $trigger_error = false, $admin = false)
	{
		global $db, $user;

		// Bulk delete - option can only be accomplished on admin pages
		if (is_array($yubikeys))
		{
			sort($yubikeys);

			$l_yubikey_list = implode(', ', $yubikeys);
			$users = array();
			$num_yubikeys = 0;

			// Retrieve corresponding user ids
			$sql = 'SELECT deviceid, user_id FROM ' . YUBIKEY_TABLE . ' WHERE ' . $db->sql_in_set('deviceid', $yubikeys) . ' ORDER BY deviceid ASC';
			$result = $db->sql_query($sql);

			while ($row = $db->sql_fetchrow($result))
			{
				$users[] = (int) $row['user_id'];
				++$num_yubikeys;
			}
			$db->sql_freeresult($result);

			// Delete the YubiKeys
			$sql = 'DELETE FROM ' . YUBIKEY_TABLE . ' WHERE ' . $db->sql_in_set('deviceid', $yubikeys);
			$db->sql_query($sql);

			if ($db->sql_affectedrows() > 0)
			{
				// Log the action
				$log_action = 'LOG_YUBIKEY' . (($num_yubikeys > 1) ? 'S' : '')  .  '_DELETED';
				add_log('admin', $log_action, $l_yubikey_list);

				for ($i = 0; $i < $num_yubikeys; ++$i)
				{
					add_log('user', $users[$i], 'LOG_YUBIKEY_DELETED', $yubikeys[$i]);
				}

				yubikey_message('YUBIKEYS_DELETED', $action, $trigger_error, false, $admin);
			}
			else
			{
				// Log the action
				$log_action = 'LOG_ERROR_DELETING_YUBIKEY' . (($num_yubikeys > 1) ? 'S' : '');
				add_log('admin', $log_action, $l_yubikey_list);

				for ($i = 0; $i < $num_yubikeys; ++$i)
				{
					add_log('user', $users[$i], 'LOG_ERROR_DELETING_YUBIKEY', $yubikeys[$i]);
				}

				yubikey_message('ERROR_DELETING_YUBIKEYS', $action, $trigger_error, true, $admin);
			}
		}
		else
		{
			// Check if YubiKey exists
			$row = yubikey_get_details($yubikeys);

			$user_id = (int) $row['user_id'];

			if ($user_id != $user->data['user_id'] && !$admin)
			{
				yubikey_message('YUBIKEY_ERROR_INVALID', $action, $trigger_error, true, $admin);
			}

			// Delete the YubiKey
			$sql = 'DELETE FROM ' . YUBIKEY_TABLE . ' WHERE deviceid = \'' . $db->sql_escape($yubikeys) . '\'';
			$db->sql_query($sql);

			if ($db->sql_affectedrows())
			{
				// Log the action
				if ($admin)
				{
					add_log('admin', 'LOG_YUBIKEY_DELETED', $yubikeys);
				}
				add_log('user', $user_id, 'LOG_YUBIKEY_DELETED', $yubikeys);

				yubikey_message('YUBIKEY_DELETED', $action, $trigger_error, false, $admin);
			}
			else
			{
				// Log the action
				add_log('user', $user_id, 'LOG_ERROR_DELETING_YUBIKEY', $yubikeys);

				yubikey_message('ERROR_DELETING_YUBIKEY', $action, $trigger_error, true, $admin);
			}
		}
	}
}

?>